<script>
import ChartNode from './render-node.js';
import { save2Image } from './downToImage';
import {
  THEME_COLORS,
  ROOT_THEME,
  POST_THEME,
  EMP_THEME
} from './theme-config.js';
import _ from 'lodash';
export default {
  inheritAttrs: false,
  components: { ChartNode },
  props: {
    treeData: [Object, Array],
    // 是否水平显示
    showDeptDisable: Boolean,
    showGwDisable: Boolean,
    horizontal: Boolean,
    showEmp: Boolean,
    showPosts: Boolean,
    // 折叠节点
    collapsable: Boolean,
    // // 展开所有,在collapsable为true下有效
    // expandAll: Boolean,
    // 是否开启导出为图片
    hasExportToImage: {
      type: Boolean,
      default: true
    },
    // 右键菜单配置
    contextMenuProps: {
      type: Object,
      default() {
        return {
          // 是否启用
          enable: true,
          menuList: []
        };
      }
    },
    // 数据配置
    props: {
      type: Object,
      default() {
        return {
          label: 'label',
          expand: 'expand',
          children: 'children',
          level: 'level',
          empInfos: 'empInfos',
          posts: 'posts'
        };
      }
    }
  },
  data() {
    return {
      isFirstLoading: true,
      // 是否应用下级
      useThemeChild: true,
      // 是否应用下级 方向
      useDirectionChild: true,
      useTheme: true,
      // 是否应用下级 方向
      useDirection: true
    };
  },
  watch: {
    // 展开节点
    expandAll(v) {
      if (!this.collapsable) {
        return;
      }
      const data = this.treeData;
      this.expandNodeAll(data, v);
    }
  },
  methods: {
    // 导出为图片
    exportToImage({ fileName = '结构图' }) {
      return new Promise((r) => {
        if (!this.hasExportToImage) {
          r(true);
          return;
        }
        this.$nextTick(() => {
          const charts = this.$refs.chartNode.$el;
          if (charts) {
            save2Image({
              dom: charts,
              fileName
            }).then((res) => {
              r(true);
            });
          }
        });
      });
    },
    // 展开折叠节点
    handleExpand(data) {
      // 判断按钮展开状态
      const hasExpand = Reflect.has(data, 'expand');
      if (hasExpand) {
        this.$set(data, 'expand', !data.expand);
        const children = data[this.props.children];
        if (!data.expand && children) {
          this.collapseDeepNode(children);
        }
      } else {
        this.$set(data, 'expand', true);
      }
    },
    // 折叠所有节点
    collapseDeepNode(children = []) {
      children.forEach((child) => {
        if (child.expand) {
          this.$set(child, 'expand', false);
        }
        const ren = child[this.props.children];
        !!ren && ren.length && this.collapseDeepNode(ren);
      });
    },
    // // 展开或者折叠所有节点
    // expandNodeAll(data, v) {
    // 	if (!!data) {
    // 		if (Array.isArray(data)) {
    // 			data.forEach((child) => {
    // 				this.$set(child, 'expand', v);
    // 				!!child.children &&
    // 					child.children.length &&
    // 					this.expandNodeAll(child.children, v);
    // 			});
    // 		} else {
    // 			this.$set(data, 'expand', v);
    // 			const children = data.children || [];
    // 			this.expandNodeAll(children, v);
    // 		}
    // 	}
    // },
    // 处理data数据层级,给每一层设置所在级别
    handleData(data, level, currentLevel) {
      var that = this;
      if (!!data) {
        if (Array.isArray(data)) {
          data = data.filter(item => {
            return item.disable == 0 || that.showDeptDisable || item.isUser || item.isPost
          })
          data.map((item) => {
            const addLevel = level + 1;
            item[this.props.level] = addLevel;
            let children = item[this.props.children] || [];
            const posts = item[this.props.posts];
            const empInfos = item[that.props.empInfos];
            if (that.showEmp && !!empInfos && empInfos.length) { that.handleEmps(item); }
            this.showPosts && !!posts && posts.length && this.handlePosts(item);
            if (!('expand' in item)) item.expand = true;
            if (!!item[this.props.children] && item[this.props.children].length != 0) {
              item[this.props.children] = this.handleData(item[this.props.children], addLevel, that.$attrs.level)
            }
            return item;
          });
        } else {
          data[this.props.level] = 0;
          const empInfos = data[that.props.empInfos];
          this.showEmp && !!empInfos && empInfos.length && this.handleEmps(data);
          const posts = data[this.props.posts];
          this.showPosts && !!posts && posts.length && this.handlePosts(data);
          let children = data[this.props.children] || [];
          children = children.filter(item => {
            return item.disable == 0 || that.showDeptDisable || item.isUser || item.isPost
          })
          data[this.props.children] = children;
          this.handleData(data[this.props.children], 0, currentLevel);
          if (this.collapsable && currentLevel > 0) if (!('expand' in data)) data.expand = true;
          data['theme'] = ROOT_THEME.value
        }
      }
      return data;
    },
    //处理人员信息
    handleEmps(data, { level1 } = {}) {
      var that = this;
      if (
        data &&
        !!data.empInfos &&
        Array.isArray(data.empInfos) &&
        data[this.props.empInfos].length
      ) {
        const level = data[this.props.level] || level1 + 1;
        const empInfos = _.cloneDeep(data[this.props.empInfos]);
        let subDepts = data[this.props.children] || [];
        subDepts = subDepts.filter(item => {
          return item.disable == 0 || that.showDeptDisable
        })
        const arr = [];
        empInfos.forEach((empInfos) => {
          arr.push({
            [this.props.label]: empInfos.a0101,
            sex: empInfos.sex == "0" ? '男' : empInfos.sex == "1" ? '女' : '',
            a0188: empInfos.a0188,
            a0188B: empInfos.a0188B,
            status: empInfos.status
          });
        });
        let tempArr = [{
          showMore: false,
          isUser: true,
          list: arr,
          vertical: true,
          headCount: 0,
          empCount: 0,
          theme: EMP_THEME.value
        }]
        Reflect.deleteProperty(data, this.props.empInfos);
        data[this.props.children] = [...subDepts, ...tempArr];
        return [...subDepts, ...tempArr];
      }
    },
    // 处理岗位信息
    handlePosts(data) {
      var that = this;
      if (
        data &&
        !!data.posts &&
        Array.isArray(data.posts) &&
        data[this.props.posts].length
      ) {
        const level = data[this.props.level];
        const posts = _.cloneDeep(data[this.props.posts]);
        let subDepts = data[this.props.children] || [];
        const arr = [];
        let userList = [];
        posts.forEach((post) => {
          const empInfos = post[that.props.empInfos];
          let tempSubDepts = [];
          if (that.showEmp && !!empInfos && empInfos.length) {
            let tempUserList = []
            tempSubDepts = that.handleEmps(post, {
              level: level
            });
            tempSubDepts.map(item => {
              if (item.list && item.list.length != 0) tempUserList.push(...item.list)
            })
            tempUserList.map(item => { userList.push(item.a0188) })
          }
          if (that.showGwDisable || post.disable == 0) {
            arr.push({
              [this.props.level]: level,
              [this.props.label]: post.mC0000,
              dept_Code: post.bM0000,
              isPost: true,
              vertical: true,
              headCount: post.e0107,
              empCount: post.headCount,
              // 岗位编制,接口未返回
              [this.props.children]: tempSubDepts,
              [this.props.expand]: true,
              theme: POST_THEME.value
            });
          }
        });
        subDepts = subDepts.filter(item => {
          if (item.isUser) {
            item.list = item.list.filter(item2 => {
              return !userList.includes(item2.a0188)
            })
          }
          return item.disable == 0 || that.showDeptDisable || item.isUser
        })
        Reflect.deleteProperty(data, this.props.posts);
        data[this.props.children] = [...subDepts, ...arr];
      }
    },
    // 更改颜色
    handleChangeTheme(data, item) {
      const { code } = item;
      // 是否应用下级
      // const useChild = Reflect.ha s(data, 'useChild');

      //未应用
      this.$set(data, 'theme', code);
      if (this.useTheme && !!data.parentCode) {
        let parent = this.observer(this.treeData.subDepts, data, this.treeData)
        !Object.prototype.toString.call(parent).includes("Array") && (parent = [parent])
        parent.map(item => {
          let children = item[this.props.children];
          !!children && children.length && this.setChildrenTheme(children, code, this.useThemeChild);
        })
      } else if (this.useThemeChild) {
        const children = data[this.props.children];
        !!children && children.length && this.setChildrenTheme(children, code);
      }
    },
    // 设置下级主题颜色
    setChildrenTheme(list, code, deep = true) {
      list.forEach((item) => {
        //未应用
        this.$set(item, 'theme', code);
        const children = item[this.props.children];
        !!children && children.length && deep && this.setChildrenTheme(children, code);
      });
    },
    // 更改方向
    handleChangeDirection(data, item) {
      if (this.horizontal) {
        return;
      }
      // 是否垂直
      const { vertical } = item;
      // 应用下级
      // data.level !== 0 && this.$set(data, 'vertical', vertical);
      data[this.props.level] !== 0 && this.$set(data, 'vertical', vertical);
      if (this.useDirection && !!data.parentCode) {
        let parent = this.observer(this.treeData.subDepts, data, this.treeData)
        !Object.prototype.toString.call(parent).includes("Array") && (parent = [parent])
        parent.map(item => {
          let children = item[this.props.children];
          !!children && children.length && this.setChildrenDirection(children, vertical, this.useDirectionChild);
        })
      }
      else if (this.useDirectionChild) {
        const children = data[this.props.children];
        !!children && children.length && this.setChildrenDirection(children, vertical);
      }
    },
    //寻找父节点
    observer(data, item, parent) {
      let callBack;
      let index = data.findIndex(item2 => {
        if (item2.dept_Code != item.dept_Code) {
          if (!item2.subDepts) return false;
          callBack = this.observer(item2.subDepts, item, data, callBack);
          if (!!callBack) return true
        } else {
          callBack = parent
          return true
        }
      })
      return callBack
    },
    // 设置下级方向
    setChildrenDirection(list, vertical, deep = true) {
      list.forEach((item) => {
        //未应用
        this.$set(item, 'vertical', vertical);
        const children = item[this.props.children];
        !!children && children.length && deep && this.setChildrenDirection(children, vertical);
      });
    },
    // 渲染checkbox按钮
    renderContextCheckboxThemeItem(h, item, data) {
      return this.renderCheckoutBox(h, item, data, 'useThemeChild');
    },
    // 渲染checkbox按钮
    renderContextCheckboxTheme(h, item, data) {
      return this.renderCheckoutBox(h, item, data, 'useTheme');
    },
    // 渲染checkbox按钮
    renderContextCheckboxDirectionItem(h, item, data) {
      return this.renderCheckoutBox(h, item, data, 'useDirectionChild');
    },
    renderContextCheckboxDirection(h, item, data) {
      return this.renderCheckoutBox(h, item, data, 'useDirection');
    },
    renderCheckoutBox(h, item, data, filed) {
      const self = this;
      return h(
        'el-checkbox',
        {
          props: {
            value: self[filed]
          },
          on: {
            click: (e) => {
              e.stopPropagation();
            },
            input: (e) => {
              self[filed] = e;
            }
          }
        },
        [item.value]
      );
    },
    // 渲染颜色按钮
    renderContextThemeItem(h, data) {
      const style = {
        display: 'inline-block',
        height: '12px',
        width: '12px',
        border: '1px solid #ddd',
        backgroundColor: data.code.colorCode
      };
      return h('span', [
        h('em', {
          style,
          domProps: {
            className: 'color-sque'
          }
        }),
        data.value
      ]);
    },
    // 处理右键菜单数据
    handleContextData() {
      const { enable, menuList } = this.contextMenuProps;

      //  设置颜色
      const themeList = THEME_COLORS.map((theme) => {
        return {
          event: 'change-theme',
          value: theme.label,
          code: theme.value,
          render: this.renderContextThemeItem
        };
      });
      //菜单数据
      const menuData = [
        {
          event: '',
          value: '主题',
          children: [
            ...themeList,
            {
              event: 'theme-use-child',
              value: '应用下级',
              render: this.renderContextCheckboxThemeItem,
              stop: true
            },
            {
              event: 'theme-use',
              value: '应用同级',
              render: this.renderContextCheckboxTheme,
              stop: true
            }
          ]
        }
      ];
      // 方向
      const directionData = {
        event: '',
        value: '方向',
        children: [
          { event: 'change-direction', value: '竖直', vertical: true },
          { event: 'change-direction', value: '水平', vertical: false },
          {
            event: 'dire-use-child',
            value: '应用下级',
            render: this.renderContextCheckboxDirectionItem,
            stop: true
          },
          {
            event: 'dire-use',
            value: '应用同级',
            render: this.renderContextCheckboxDirection,
            stop: true
          }
        ]
      };
      if (!this.horizontal) {
        menuData.push(directionData);
      }
      return { enable, menuList: [...menuData, ...menuList] };
    }
  },
  render(h) {
    const {
      horizontal,
      collapsable,
      treeData,
      $attrs,
      $props,
      $listeners,
      handleExpand,
      handleData,
      handleContextData,
      handleChangeTheme,
      handleChangeDirection
    } = this;
    // 外层样式
    const cls = ['chart-wrapper'];
    // 内层样式
    const chartsCls = ['org-chart'];

    horizontal
      ? cls.push('horizontal') && chartsCls.push('horizontal')
      : cls.push('vertical');
    collapsable && chartsCls.push('collapsable');
    // debugger;
    // 处理data
    if (Object.keys(this.treeData).length != 0) {
      let tempData = _.cloneDeep(this.treeData);
      tempData = handleData(tempData, 0, $attrs.level);
      let tempJSON = JSON.stringify(this.treeData);
      let tempJSONB = JSON.stringify(tempData);
      if (tempJSON != tempJSONB) {
        this.$emit('update:treeData', tempData);
        return;
      }
    } else {
      return;
    }
    // console.log('====================================');
    // console.log($attrs.data);
    // console.log('====================================');
    // 处理右键菜单数据

    const contextData = handleContextData();
    return h(
      'div',
      {
        domProps: {
          className: cls.join(' ')
        },
        ref: 'chart'
      },
      [
        h(
          'div',
          {
            domProps: {
              className: 'org-chart-container sg-chart'
            }
          },
          [
            h(
              'div',
              {
                domProps: {
                  className: chartsCls.join(' ')
                }
              },
              [
                h('chart-node', {
                  ref: 'chartNode',
                  props: {
                    horizontal,
                    collapsable,
                    contextMenuProps: contextData,
                    props: $props.props,
                    data: treeData,
                    ...$attrs
                  },
                  on: {
                    // 点击展开节点触发
                    'on-expand': (data) => {
                      handleExpand(data);
                    },
                    // 颜色改变的时候触发
                    'context-click-change-theme': (data, item) => {
                      handleChangeTheme(data, item);
                    },
                    'context-click-change-direction': (data, item) => {
                      handleChangeDirection(data, item);
                    },
                    ...$listeners
                  }
                })
              ]
            )
          ]
        )
      ]
    );
  }
};
</script>
<style lang="less" >
@import url(./index.less);
</style>